import re
import random
from flask import current_app, jsonify
from flask import make_response
from flask import request
from flask import session

from info import constants, db
from info import redis_store
from info.models import User
from info.modules.passport import passport_blue
from libs.yuntongxun.sms import CCP
from utils.captcha.captcha import captcha
from utils.response_code import RET
from datetime import datetime

# 功能说明：退出
# 请求方式：post
# 请求路径：passport/logout
# 请求参数：无
# 返回参数：errno,errmsg
@passport_blue.route('/logout', methods=['POST'])
def logout():

    # 1 清除session中的值，暴力方式session.clear(),不推荐
    session.pop("user_id")
    session.pop('mobile')
    session.pop("nick_name")
    # session.clear()

    # 返回响应
    return jsonify(errno=RET.OK,errmsg='退出成功')



# 功能说明：登陆
# 请求方式：POST
# 请求路径：passport/login
# 请求参数：mobile,password
# 返回参数：errno,errmsg
@passport_blue.route('/login', methods=['POST'])
def login():

    # 获取参数
    mobile = request.json.get('mobile')
    password = request.json.get('password')

    #　判断参数不为空
    if not all([mobile,password]):
        return jsonify(errno=RET.DATAERR,errmsg='请求参数不全')

    # 根据mobile获取数据库中的用户
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='获取用户信息失败')

    # 判断客户是否存在
    if not user:
        return jsonify(errno=RET.DATAERR,errmsg='该用户不存在')

    # 判断用户密码是否相等
    # if user.password_hash != password:　# 密码不加密验证方式
    if not user.check_password(password): # 密码加密验证方式，check_password()方法模型类中已写好此方法，返回的是True,或False
        return jsonify(errno=RET.DATAERR,errmsg='密码不正确')

    # 保存用户登陆状态
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    session['mobile'] = user.mobile

    # 记录客户最后登陆时间,并设置数据库自动提交属性
    user.last_login = datetime.now()

    # 返回响应
    return jsonify(errno=RET.OK,errmsg='登陆成功')



# 功能分析：注册用户
# 请求方式：POST
# 请求路径：passport/register
# 请求参数:mobile,sms_code,password
# 返回参数：errno,errmsg

@passport_blue.route('/register', methods=['POST'])
def register():

    # 获取参数
    mobile = request.json.get('mobile')
    sms_code = request.json.get('sms_code')
    password = request.json.get('password')

    # 验证参数，不为空验证
    if not all([mobile,sms_code,password]):
        return jsonify(errno=RET.DATAERR,errmsg='参数不全')

    # 手机号验证
    if not re.match('1[3578]\\d{9}',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='手机号格式不对')

    # 获取redis中的sms_code,如果存在并移除
    try:
        redis_sms_code = redis_store.get("sms_code:%s"%mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='获取数据库验证码失败')

    # 判断验证码是否过期
    if not redis_sms_code:
        return jsonify(errno=RET.DATAERR,errmsg='短信验证码过期')

    # 删除验证码
    try:
        redis_store.delete('sms_code:%s'%mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='验证码删除失败')

    # 判断验证码是否正确
    if redis_sms_code != sms_code:
        return jsonify(errno=RET.DATAERR,errmsg='验证码错误')

    # 创建用户数据
    user = User()
    user.nick_name = '新经资讯'+mobile
    # user.password_hash = password  #　密码不加密
    # 设置密码加密,user.password后台其实调用的是password方法
    user.password = password
    user.mobile = mobile
    user.signature = '你爱大海，我爱你；你爱森林，我绿过你'

    # 添加到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DATAERR,errmsg='用户创建失败')

    # 返回数据
    return jsonify(errno=RET.OK,errmsg='用户注册成功')




# 功能分析：获取短信验证码,借助云通讯
# 请求方式：POST
# 请求路径：passport/sms_code
# 请求参数：mobile,image_code,image_code_id
# 返回参数：errno.errmsg

@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():

    # 获取参数
    mobile = request.json.get('mobile')
    image_code = request.json.get('image_code')
    image_code_id = request.json.get('image_code_id')

    # 1 不为空判断
    if not all([mobile,image_code,image_code_id]):
        return jsonify(errno=RET.DATAERR,errmsg='请求参数不全')

    # 2判断电话是否正确
    if not re.match('1[3578]\\d{9}',mobile):
        return jsonify(errno=RET.DATAERR,errmsg='手机号格式不对')

    #3 根据image_code_id取出redis_image_code
    try:
        redis_image_code = redis_store.get('image_code:%s'%image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='获取数据库验证码失败')

    # ４　如果验证码存在则删除
    try:
        redis_store.delete('image_code:%s'%image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='验证码删除失败')

    # ５　比较数据库验证码和和输入是否一致
    if redis_image_code.upper() != image_code.upper():
        return jsonify(errno=RET.DATAERR,errmsg='验证码不正确')

    # ６生成随机数
    sms_code = '%06d'%random.randint(0,999999)
    current_app.logger.error(sms_code)
    # 7　使用云通讯发送短信
    # try:
    #     ccp = CCP()
    #     result = ccp.send_template_sms('18366101283',[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],1)
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.DATAERR,errmsg='云通讯异常')
    #
    # # ８判断短信是否发送成功
    # if result == -1:
    #     return jsonify(errno=RET.DATAERR,errmsg='短信发送失败')

    # ９　把验证码存储到redis数据库中,并设置有效时间且与短信提示有效时间一直
    try:
        redis_store.set('sms_code:%s'%mobile,sms_code,constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR,errmsg='短信验证码存储失败')

    # 10 返回信息
    return jsonify(errno=RET.OK,errmsg='发送成功')




# 功能分析：获取图片验证码，借助工具包captcha
# 请求方式：get
# 请求路径：passport/image_code
# 请求参数：cur_ip,pre_ip
# 返回参数：图片信息

@passport_blue.route('/image_code')
def image_code():
    # 1.获取参数，这个而是通过图片链接的方式请求过来的，所以参数在请求路径后面，用request.args获取
    cur_id = request.args.get('cur_id')
    pre_id = request.args.get('pre_id')

    if not cur_id:
        return '参数不全'

    # 2.借助captcha生成验证码图片
    name, text, image_code = captcha.generate_captcha()

    # 3.将图片当前id存储到redis数据库中,key,value,图片最大有效时间
    try:
        redis_store.set('image_code:%s' % cur_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)

        # 4判断之前验证码是否存在，如果存在则删除
        if pre_id:
            redis_store.delete('image_code:%s' % pre_id)
    except Exception as e:
        current_app.logger.error(e)
        return '图片存储失败'

    # 5.返回验证码图片,并且设置返回格式
    response = make_response(image_code)
    response.headers['Content-Type'] = 'image/png'
    return response
